#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"

// 机器模式定时器中断向量
extern void timervec(void);

// 每个 hart 的机器模式 scratch 区，供 timervec 使用
// scratch[hart][0] = mtimecmp 地址
// scratch[hart][1] = 触发间隔（cycle）
// scratch[hart][2] = mtime 地址
static uint64 timer_scratch[NCPU][3];

void start(void)
{
  // 当前 hart
  int id = (int)r_mhartid();

  // 委托异常/中断、PMP 等
  w_medeleg(0xffff);
  w_mideleg((1 << 1) | (1 << 5) | (1 << 9));
  w_pmpaddr0(~0ULL >> 2);
  w_pmpcfg0(0xF);

  // 将 hartid 保存在 tp，供 S 态使用（xv6 风格）
  asm volatile("mv tp, %0" :: "r"(id));

  // 切到 S 模式，从 main 开始
  w_mepc((uint64)main);
  w_mstatus((r_mstatus() & ~MSTATUS_MPP_MASK) | MSTATUS_MPP_S);

  // 配置机器定时器中断（M 态处理，并注入 SSIP 到 S）
  const uint64 interval = 1000000;
  w_mtvec((uint64)timervec);
  timer_scratch[id][0] = (uint64)CLINT_MTIMECMP_ADDR(id);
  timer_scratch[id][1] = interval;
  timer_scratch[id][2] = (uint64)CLINT_MTIME_ADDR;
  w_mscratch((uint64)&timer_scratch[id][0]);

  uint64 now = *(volatile uint64*)CLINT_MTIME_ADDR;
  *(volatile uint64*)CLINT_MTIMECMP_ADDR(id) = now + interval;

  w_mie(r_mie() | MIE_MTIE);
  w_mstatus(r_mstatus() | MSTATUS_MIE);

  asm volatile("mret");
}